// Loggr::Tools::Filer
// Tools make Loggr be more autonomous.
// By George Ulyanov (c) 2010

#include "Config.h"

#ifndef LOGGR_TOOLS_FILER_H_
#   include "Filer.h"
#endif

#if defined (LOGGR_WIN32API)
#	include <Windows.h>
#elif defined (LOGGR_OTHER)
#	include <stdlib.h>
#endif
#include <stdexcept>

namespace Loggr
{
    namespace Tools
    {
        struct FilerData
        {
#if defined (LOGGR_WIN32API)
            HANDLE m_file;
#elif defined (LOGGR_OTHER)
            FILE *m_file;
#endif
        };

        Filer::Filer()
        {
            m_data = new FilerData();
            if (!m_data)
            {
                throw std::runtime_error("Couldn't initialize Filer::FilerData.");
            }

#if defined (LOGGR_WIN32API)
            // Retrieve a current directory first
            std::string currDir;
            char tmp[MAX_PATH + 1];
            ::GetModuleFileNameA(0, tmp, MAX_PATH);
            currDir.assign(tmp);
            
            // Update slashes
            int slashPos = currDir.find_last_of('/');
            if (slashPos == currDir.npos)
            {
                slashPos = currDir.find_last_of('\\');
            }
            if (slashPos != currDir.npos)
            {
                currDir.erase(slashPos, currDir.size() - slashPos);
            }

            // Prepare file name that doesn't already exist
            char fileName[1024];
            for (size_t i = 1; i < ((size_t)0) - 1; ++i)
            {
                sprintf(fileName, "%s/log_%06u.txt", currDir.c_str(), i);
                FILE* ftmp = fopen(fileName, "r"); // TODO:
                if (ftmp)
                {
                    fclose(ftmp);
                }
                else
                {
                    break;
                }
            }

            // All done
            m_data->m_file = ::CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
            if (m_data->m_file == INVALID_HANDLE_VALUE)
#elif defined (LOGGR_OTHER)
            m_data->m_file = fopen(fileName, "w+");
            if (!m_data->m_file)
#endif
            {
                throw std::runtime_error("Filer: Couldn't open a file.");
            }
        }

        Filer::~Filer() throw()
        {
#if defined (LOGGR_WIN32API)
            ::CloseHandle(m_data->m_file);
#elif defined (LOGGR_OTHER)
            fclose(m_data->m_file);
#endif
            delete m_data;
        }

        void Filer::Write(const char *buffer, const size_t bufferSize)
        {
#if defined (LOGGR_WIN32API)
            DWORD written = 0;
            ::WriteFile(m_data->m_file, buffer, bufferSize, &written, 0);
            ::FlushFileBuffers(m_data->m_file);
#elif defined (LOGGR_OTHER)
            fwrite(buffer, sizeof(char), bufferSize, m_data->m_file);
#endif
            return;
        }
    }
    // namespace Tools
}
// namespace Loggr
